/**
 * 
 */
package pATT.profilingAlgorithm;

import java.util.Vector;

import pATT.BasicAlgorithm.classifiers.tree.J48;
import pATT.BasicAlgorithm.classifiers.tree.j48.C45PruneableClassifierTree;
import pATT.BasicAlgorithm.classifiers.tree.j48.C45Split;
import pATT.BasicAlgorithm.classifiers.tree.j48.ClassifierSplitModel;
import pATT.BasicAlgorithm.classifiers.tree.j48.ClassifierTree;
import pATT.core.Attribute;
import pATT.core.FastVector;
import pATT.core.Instances;
import pATT.core.Utils;
import pATT.profile.ComponentLeaf;
import pATT.profile.ComponentNode;
import pATT.profile.ComponentTree;
import pATT.profile.Profile;

/**
 * @author Ignacio
 *
 */
public class ECTree extends BatchAlgorithm {
	
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private ClassifierTree m_tree = null;
	private String classLeaf = "";
	
	private Vector vector = null;
	
	public ECTree() {
		super.typeAlgorithm = CLASSIFIER_TREE;
	}
	
	
	/** 
	 */
	@Override
	public String toText() {
		
		return ((ComponentTree)vector.get(0)).toText().toString();
	}
	
	/* (non-Javadoc)
	 * @see pATT.profilingAlgorithm.BatchAlgorithm#basicAlgorithmOutput()
	 */
	@Override
	public String basicAlgorithmOutput() {
		String text=new String();
		text +="-----------------\n";
		text += basicAlgorithm.toString();
		return text;
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public Profile run(Instances input) {
		if(input.numInstances()>0){
			Attribute attClass = input.attribute(getClassLeaf().trim());
			if(attClass != null){
				input.setClassIndex(attClass.index());
			}
			
			Profile output=new Profile(input);
			try{
				basicAlgorithm.build(input);
				m_tree  = (ClassifierTree)basicAlgorithm.getResults();
				
				Vector<ComponentTree> components = new Vector<ComponentTree>();
				ComponentTree component = null;
				if(m_tree.isM_isLeaf()){
					ClassifierSplitModel localModel = m_tree.localModel();
					String valueAttSon = input.classAttribute().value(localModel.distribution().maxClass());
					//				valueAttSon = input.classAttribute().value(localModel.distribution().maxClass(0));
					Attribute attSon = input.classAttribute();
					
					double valueExist = Utils.roundDouble(localModel.distribution().perBag(0),2);
					double valueNotExist = Utils.roundDouble(localModel.distribution().numIncorrect(0),2);
					component = new ComponentLeaf(attSon.name(), valueAttSon, valueExist, valueNotExist);
					
					
					
				}else{
					
					int attIndex = ((C45Split)m_tree.localModel()).attIndex();
					Attribute att = input.attribute(attIndex);
//					Enumeration enumRamas = att.enumerateValues();
					FastVector enumRamas = att.getValues();
					for (int i = 0; i < m_tree.sonsSize(); i++) {
						C45PruneableClassifierTree son = (C45PruneableClassifierTree)m_tree.son(i);
						ComponentTree comp = makeComponent(son,input);
						components.addElement(comp);
					}
					component = new ComponentNode(att.name(),components, enumRamas);
				}
				vector = new Vector();
				vector.addElement(component);
				output.update(vector);
				
			}
			catch (Exception ex){
				return null;
			}
			return output;
			}
			else{
				return null;
			}
		}
		
		
		private ComponentTree makeComponent(C45PruneableClassifierTree tree, Instances input) {
			if(tree.isM_isLeaf()){
				//return leaf
				ClassifierSplitModel localModel = tree.localModel();
				String valueAttSon = input.classAttribute().value(localModel.distribution().maxClass());
//				valueAttSon = input.classAttribute().value(localModel.distribution().maxClass(0));
				Attribute attSon = input.classAttribute();
				
				double valueExist = Utils.roundDouble(localModel.distribution().perBag(0),2);
				double valueNotExist = Utils.roundDouble(localModel.distribution().numIncorrect(0),2);
				ComponentTree comp = new ComponentLeaf(attSon.name(), valueAttSon, valueExist, valueNotExist);
				return comp;
				
				
			}
			
			Vector<ComponentTree> components = new Vector<ComponentTree>();
			ComponentTree component = null;
			int attIndex = ((C45Split)tree.localModel()).attIndex();
			Attribute att = input.attribute(attIndex);
//			Enumeration enumRamas = att.enumerateValues();
			FastVector enumRamas = att.getValues();
			for (int i = 0; i < tree.sonsSize(); i++) {
				C45PruneableClassifierTree son = (C45PruneableClassifierTree)tree.son(i);
				ComponentTree comp = makeComponent(son,input);
				components.addElement(comp);
			}
			component = new ComponentNode(att.name(),components, enumRamas);
			
			return component;
		}
		
		
		public String getClassLeaf() {
			return classLeaf;
		}
		
		
		public void setClassLeaf(String classLeaf) {
			this.classLeaf = classLeaf;
		}
		
		public String getGraph(){
			if(this.basicAlgorithm != null){
			try {
				return ((J48)this.basicAlgorithm).graph();
			} catch (Exception e) {
				e.printStackTrace();
			}
			}
			return "";
		}
		
		
		@Override
		public boolean needArffFile() {
			return true;
		}
		
	}
